package com.foreverwin.mes.production.service.impl;


import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.foreverwin.mes.common.constants.HandleBOConstants;
import com.foreverwin.mes.core.exception.BusinessException;
import com.foreverwin.mes.core.utils.DateUtil;
import com.foreverwin.mes.core.utils.StringUtils;
import com.foreverwin.mes.core.utils.TimeUtils;
import com.foreverwin.mes.meapi.dto.ShiftResult;
import com.foreverwin.mes.meapi.model.WorkCenter;
import com.foreverwin.mes.meapi.service.UserShiftService;
import com.foreverwin.mes.meapi.service.WorkCenterService;
import com.foreverwin.mes.production.mapper.WorkCenterShiftMapper;
import com.foreverwin.mes.production.model.WorkCenterShift;
import com.foreverwin.mes.production.model.WorkCenterShiftView;
import com.foreverwin.mes.production.service.WorkCenterShiftService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 工作中心班次设定 服务实现类
 * </p>
 *
 * @author syngna
 * @since 2018-12-14
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class WorkCenterShiftServiceImpl extends ServiceImpl<WorkCenterShiftMapper, WorkCenterShift> implements WorkCenterShiftService {

    @Autowired
    private UserShiftService userShiftService;
    @Autowired
    private WorkCenterService workCenterService;
    @Autowired
    private WorkCenterShiftMapper workCenterShiftMapper;

    @Override
    public WorkCenterShift selectOne(WorkCenterShift workCenterShift) {
        return workCenterShiftMapper.selectOne(workCenterShift);
    }

    @Override
    public List<WorkCenterShiftView> getWCShiftList(String site, String workCenter) {

        //查询所有班次
        Locale locale = LocaleContextHolder.getLocale();
        List<WorkCenterShiftView> list = workCenterShiftMapper.selectWCShiftList(site, workCenter, locale.getLanguage());
        return this.resetUserShiftDateTime(list);
    }

    @Override
    public void saveWorkCenterShift(String site, String user, WorkCenterShift workCenterShift) throws BusinessException {

        //nowDate
        Date nowDate = new Date();
        String shift = workCenterShift.getShift();
        String workCenter = workCenterShift.getWorkCenter();

        //查询工作中心是否存在
        String workCenterBo = StringUtils.genHandle(HandleBOConstants.WORK_CENTER_BO, site, workCenter);
        WorkCenter workCenterModel = workCenterService.selectById(workCenterBo);
        if (workCenterModel == null) {
            throw BusinessException.build("工作中心【" + workCenter + "】未维护");
        }

        //查询当前班次时间区间
        ShiftResult shiftResult = userShiftService.getUserShiftDefinitionByShift(site, shift);
        if (shiftResult == null) {
            throw BusinessException.build("班次【 " + shift + "】未维护");
        }
        BigDecimal shiftBegin = new BigDecimal(shiftResult.getShiftBegin());
        BigDecimal shiftEnd = new BigDecimal(shiftResult.getShiftEnd());

        //校验设定存在
        WorkCenterShift queryModel = new WorkCenterShift();
        queryModel.setSite(site);
        queryModel.setWorkCenter(workCenter);
        queryModel.setShift(shift);
        queryModel = workCenterShiftMapper.selectOne(queryModel);
        if (queryModel != null) {
            throw BusinessException.build("工作中心【" + workCenter + "】已经设定了班次【" + shift + "】");

        }

        //校验工作中心下班次时间不能重叠
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("SITE", site);
        paramMap.put("WORK_CENTER", workCenter);
        Locale locale = LocaleContextHolder.getLocale();
        List<WorkCenterShiftView> workCenterShiftList = workCenterShiftMapper.selectEnabledShiftsByWorkCenter(site, workCenter, locale.getLanguage());
        if (workCenterShiftList != null && workCenterShiftList.size() > 0) {

            validateCrossSetting(shift, shiftBegin, shiftEnd, workCenterShiftList);
        }


        //保存
        WorkCenterShift addModel = new WorkCenterShift();
        String handle = "WorkCenterShiftBO:" + site + "," + workCenter + "," + shift;
        addModel.setHandle(handle);
        addModel.setSite(site);
        addModel.setWorkCenter(workCenter);
        addModel.setShift(shift);
        addModel.setStatus("Y");
        addModel.setCreateUser(user);
        addModel.setCreatedDateTime(nowDate);
        addModel.setModifyUser(user);
        addModel.setModifiedDateTime(nowDate);
        insert(addModel);
    }


    @Override
    public Map<String, Object> getCurrentShiftOfResource(String site, String resource, Date currentDate) throws BusinessException {

        String shift;
        Map<String, Object> returnMap;

        // 查询资源所属工作中心
        String resourceBo = StringUtils.genHandle(HandleBOConstants.RESOURCE_BO, site, resource);
        WorkCenter workCenterModel = workCenterService.getWorkCenterByWorkCenterOrResource(resourceBo);
        if (workCenterModel == null) {
            throw BusinessException.build("设备【" + resource + "】没有分配到工作中心！");
        }

        // 查询工作中心维护的班次
        List<WorkCenterShiftView> list = new ArrayList<>();
        if ("LEVEL5".equals(workCenterModel.getWcCategory())) {
            list = this.getEnabledShiftsByWorkCenter(site, workCenterModel.getWorkCenter());
        } else {
            List<WorkCenter> wcList = workCenterService.getParent(workCenterModel.getHandle());
            if (wcList == null || wcList.size() <= 0)
                throw BusinessException.build("设备【" + resource + "】所属工作中心主数据维护不完整！");
            for (int i = 0; i < wcList.size(); i++) {
                workCenterModel = wcList.get(i);
                if ("LEVEL5".equals(workCenterModel.getWcCategory())) {

                    list = this.getEnabledShiftsByWorkCenter(site, workCenterModel.getWorkCenter());
                    break;
                } else continue;
            }
        }
        if (list.size() <= 0) {
            throw BusinessException.build("设备【" + resource + "】所属工作中心未设定班次！");
        }

        //遍历设备下班次，获取当前班次
        for (WorkCenterShiftView map : list) {

            returnMap = new HashMap<>();
            int shiftBegin = Integer.parseInt(map.getShiftBegin());
            int shiftEnd = Integer.parseInt(map.getShiftEnd());

            //获取当前时间-计算时间和值
            SimpleDateFormat sdfHour = new SimpleDateFormat("HH");
            int hour = Integer.parseInt(sdfHour.format(currentDate));
            SimpleDateFormat sdfMinutes = new SimpleDateFormat("mm");
            int minutes = Integer.parseInt(sdfMinutes.format(currentDate));
            SimpleDateFormat sdfSeconds = new SimpleDateFormat("ss");
            int seconds = Integer.parseInt(sdfSeconds.format(currentDate));
            int currentTime = hour * 3600 + minutes * 60 + seconds;

            String dateYMD = DateUtil.formatDate(currentDate, "yyyy-MM-dd");
            if (shiftBegin <= shiftEnd && ((currentTime >= shiftBegin && currentTime < shiftEnd))) {
                //班次区间不跨天
                shift = map.getShift();
                returnMap.put("beginTime", DateUtil.parseSimpleDateTime(dateYMD + " " + map.getBeginTime()));
                returnMap.put("endTime", DateUtil.parseSimpleDateTime(dateYMD + " " + map.getEndTime()));
                returnMap.put("shift", shift);
                returnMap.put("shiftDesc", map.getShiftDescription());
                return returnMap;
            } else if (shiftBegin > shiftEnd) {

                if (currentTime >= shiftBegin) {
                    //班次区间跨天
                    shift = map.getShift();
                    returnMap.put("beginTime", DateUtil.parseSimpleDateTime(dateYMD + " " + map.getBeginTime()));
                    returnMap.put("endTime", DateUtil.parseSimpleDateTime(DateUtil.convertToStr(DateUtil.setDate(currentDate, 0, 0, 1)) + " " + map.getEndTime()));
                    returnMap.put("shift", shift);
                    returnMap.put("shiftDesc", map.getShiftDescription());
                    return returnMap;
                } else if (currentTime < shiftEnd) {
                    shift = map.getShift();
                    returnMap.put("beginTime", DateUtil.parseSimpleDateTime(DateUtil.convertToStr(DateUtil.setDate(currentDate, 0, 0, -1)) + " " + map.getBeginTime()));
                    returnMap.put("endTime", DateUtil.parseSimpleDateTime(dateYMD + " " + map.getEndTime()));
                    returnMap.put("shift", shift);
                    returnMap.put("shiftDesc", map.getShiftDescription());
                    return returnMap;
                }
            }
        }
        return null;
    }

    @Override
    public Map<String, Object> getAppointOrCurrentShiftOfResource(String site, String resource, Date currentDate) throws BusinessException {

        String shift;
        Map<String, Object> returnMap;

        //查询资源所属工作中心
        String resourceBo = StringUtils.genHandle(HandleBOConstants.RESOURCE_BO, site, resource);
        WorkCenter workCenterModel = workCenterService.getWorkCenterByWorkCenterOrResource(resourceBo);
        if (workCenterModel == null) {
            throw BusinessException.build("设备【" + resource + "】没有分配到工作中心！");
        }

        //查询工作中心维护的班次
        List<WorkCenterShiftView> list = new ArrayList<>();
        List<WorkCenter> wcList = workCenterService.getParent(workCenterModel.getHandle());
        if (wcList == null || wcList.size() <= 0) throw BusinessException.build("设备【" + resource + "】所属工作中心主数据层级维护不完整！");
        for (int i = 0; i < wcList.size(); i++) {
            workCenterModel = wcList.get(i);
            if ("LEVEL5".equals(workCenterModel.getWcCategory())) {

                list = this.getEnabledShiftsByWorkCenter(site, workCenterModel.getWorkCenter());
                break;
            } else continue;
        }
        if (list.size() <= 0) {
            throw BusinessException.build("设备【" + resource + "】所属工作中心未设定班次！");
        }


        //获取当前时间-计算时间和值
        SimpleDateFormat sdfHour = new SimpleDateFormat("HH");
        int hour = Integer.parseInt(sdfHour.format(currentDate));
        SimpleDateFormat sdfMinutes = new SimpleDateFormat("mm");
        int minutes = Integer.parseInt(sdfMinutes.format(currentDate));
        SimpleDateFormat sdfSeconds = new SimpleDateFormat("ss");
        int seconds = Integer.parseInt(sdfSeconds.format(currentDate));
        int currentTime = hour * 3600 + minutes * 60 + seconds;


        List<Map> currentShiftList = new ArrayList<>();
        //遍历设备下班次，获取当前班次
        for (WorkCenterShiftView map : list) {

            returnMap = new HashMap<>();
            int shiftBegin = Integer.parseInt(map.getShiftBegin());
            int shiftEnd = Integer.parseInt(map.getShiftEnd());

            int appointShiftBegin = shiftBegin;
            //判断是否在预约区间
            if (StringUtils.notBlank(map.getClockInStart())) {
                int clockIn = Integer.parseInt(map.getClockInStart());
                if (clockIn < shiftBegin && currentTime >= clockIn && currentTime < shiftBegin) {

                    returnMap.put("isAppointment", "Y");
                    appointShiftBegin = clockIn;
                } else if (clockIn > shiftBegin && (currentTime > clockIn || currentTime < shiftBegin)) {

                    returnMap.put("isAppointment", "Y");
                    appointShiftBegin = clockIn;
                } else {

                    returnMap.put("isAppointment", "N");
                    appointShiftBegin = shiftBegin;
                }
            }

            String dateYMD = DateUtil.formatDate(currentDate, "yyyy-MM-dd");
            if (shiftBegin <= shiftEnd && (currentTime >= appointShiftBegin && currentTime < shiftEnd)) {

                //班次区间不跨天
                shift = map.getShift();
                returnMap.put("beginTime", DateUtil.parseSimpleDateTime(dateYMD + " " + map.getBeginTime()));
                returnMap.put("endTime", DateUtil.parseSimpleDateTime(dateYMD + " " + map.getEndTime()));
                returnMap.put("shift", shift);
                currentShiftList.add(returnMap);
                continue;
            } else if (shiftBegin > shiftEnd) {

                if (currentTime >= appointShiftBegin) {
                    //班次区间跨天
                    shift = map.getShift();
                    returnMap.put("beginTime", DateUtil.parseSimpleDateTime(dateYMD + " " + map.getBeginTime()));
                    returnMap.put("endTime", DateUtil.parseSimpleDateTime(DateUtil.convertToStr(DateUtil.setDate(currentDate, 0, 0, 1)) + " " + map.getEndTime()));
                    returnMap.put("shift", shift);
                    currentShiftList.add(returnMap);
                    continue;
                } else if (currentTime < shiftEnd) {
                    shift = map.getShift();
                    returnMap.put("beginTime", DateUtil.parseSimpleDateTime(DateUtil.convertToStr(DateUtil.setDate(currentDate, 0, 0, -1)) + " " + map.getBeginTime()));
                    returnMap.put("endTime", DateUtil.parseSimpleDateTime(dateYMD + " " + map.getEndTime()));
                    returnMap.put("shift", shift);
                    currentShiftList.add(returnMap);
                    continue;
                }
            }
        }// end for

        // 先取满足预约班次时段
        if (currentShiftList.size() > 0) {
            for (Map map : currentShiftList) {
                if ("Y".equals(map.get("isAppointment"))) {
                    return map;
                }
            }
            return currentShiftList.get(0);
        } else {
            return null;
        }
    }

    @Override
    public void updateBatchHandles(String status, String modifyUser, Date modifiedDateTime, List<String> handles) throws BusinessException {

        if ("Y".equals(status)) {
            //生效
            for (int i = 0; i < handles.size(); i++) {

                String handle = handles.get(i);
                WorkCenterShift workCenterShift = workCenterShiftMapper.selectById(handle);
                if (workCenterShift != null && !"Y".equals(workCenterShift.getStatus())) {

                    //查询参数
                    String site = workCenterShift.getSite();
                    String workCenter = workCenterShift.getWorkCenter();
                    String shift = workCenterShift.getShift();

                    //查询当前班次时间区间
                    ShiftResult shiftResult = userShiftService.getUserShiftDefinitionByShift(site, shift);
                    if (shiftResult == null) {
                        throw BusinessException.build("班次【 " + shift + "】未维护");
                    }
                    BigDecimal shiftBegin = new BigDecimal(shiftResult.getShiftBegin());
                    BigDecimal shiftEnd = new BigDecimal(shiftResult.getShiftEnd());

                    //校验存在
                    WorkCenterShift queryModel = new WorkCenterShift();
                    queryModel.setSite(site);
                    queryModel.setWorkCenter(workCenter);
                    queryModel.setShift(shift);
                    queryModel.setStatus("Y");
                    WorkCenterShift wcShift = workCenterShiftMapper.selectOne(queryModel);
                    if (wcShift != null) {
                        throw BusinessException.build("工作中心【" + workCenter + "】已经设定了有效的班次【" + shift + "】");
                    }

                    //校验工作中心下班次时间不能重叠
                    Map<String, Object> paramMap = new HashMap<>();
                    paramMap.put("SITE", site);
                    paramMap.put("WORK_CENTER", workCenter);
                    Locale locale = LocaleContextHolder.getLocale();
                    List<WorkCenterShiftView> workCenterShiftList = workCenterShiftMapper.selectEnabledShiftsByWorkCenter(site, workCenter, locale.getLanguage());
                    if (workCenterShiftList != null && workCenterShiftList.size() > 0) {

                        validateCrossSetting(shift, shiftBegin, shiftEnd, workCenterShiftList);
                    }
                }
            }

        }
        workCenterShiftMapper.updateByHandles(handles, status, modifyUser, modifiedDateTime);
    }


    public void validateCrossSetting(String shift, BigDecimal curShiftBegin, BigDecimal curShiftEnd, List<WorkCenterShiftView> list) throws BusinessException {

        BigDecimal nextCurShiftBegin = null;
        BigDecimal nextCurShiftEnd = null;
        if (curShiftBegin.compareTo(curShiftEnd) > 0) {

            //23:00~08:00拆分23:00~24:00 + 00:00~08:00
            nextCurShiftBegin = new BigDecimal("0");
            nextCurShiftEnd = curShiftEnd;

            curShiftEnd = new BigDecimal(24 * 3600);
        }

        //New List
        List<Map<String, Object>> newList = new ArrayList<>();
        if (list != null && list.size() > 0) {

            for (int i = 0; i < list.size(); i++) {
                Map<String, Object> wcShiftMap1 = new HashMap<>();
                WorkCenterShiftView wcShiftMap = list.get(i);
                String wcShift = (String) wcShiftMap.getShift();
                BigDecimal wcShiftBegin = new BigDecimal(wcShiftMap.getShiftBegin());
                BigDecimal wcShiftEnd = new BigDecimal(wcShiftMap.getShiftEnd());
                wcShiftMap1.put("shift", wcShift);
                wcShiftMap1.put("shiftBegin", wcShiftBegin);
                wcShiftMap1.put("shiftEnd", wcShiftEnd);
                if (wcShiftBegin.compareTo(wcShiftEnd) > 0) {

                    wcShiftMap1.put("shift", wcShift);
                    wcShiftMap1.put("shiftBegin", 0);
                    wcShiftMap1.put("shiftEnd", wcShiftEnd);
                    newList.add(wcShiftMap1);

                    //拆分出来的新时间
                    wcShiftMap1 = new HashMap<>();
                    wcShiftMap1.put("shift", wcShift);
                    wcShiftMap1.put("shiftBegin", wcShiftBegin);
                    wcShiftMap1.put("shiftEnd", 24 * 3600);
                    newList.add(wcShiftMap1);
                } else {

                    newList.add(wcShiftMap1);
                }
            }

            for (int j = 0; j < newList.size(); j++) {

                Map<String, Object> wcShiftMap = newList.get(j);
                String wcShift = (String) wcShiftMap.get("shift");
                BigDecimal startTime = new BigDecimal(wcShiftMap.get("shiftBegin") + "");
                BigDecimal endTime = new BigDecimal(wcShiftMap.get("shiftEnd") + "");

                if ((startTime.compareTo(curShiftBegin) > 0 && startTime.compareTo(curShiftEnd) < 0) ||
                        (endTime.compareTo(curShiftBegin) > 0 && endTime.compareTo(curShiftEnd) < 0) ||
                        (startTime.compareTo(curShiftBegin) < 0 && endTime.compareTo(curShiftEnd) >= 0) ||
                        (startTime.compareTo(curShiftBegin) <= 0 && endTime.compareTo(curShiftEnd) > 0)) {
                    throw BusinessException.build("班次【" + shift + "】与工作中心下已存在班次【" + wcShift + "】时间交叉");
                }

                if (nextCurShiftBegin != null && nextCurShiftEnd != null) {
                    if ((startTime.compareTo(nextCurShiftBegin) > 0 && startTime.compareTo(nextCurShiftEnd) < 0) ||
                            (endTime.compareTo(nextCurShiftBegin) > 0 && endTime.compareTo(nextCurShiftEnd) < 0) ||
                            (startTime.compareTo(nextCurShiftBegin) < 0 && endTime.compareTo(nextCurShiftEnd) >= 0) ||
                            (startTime.compareTo(nextCurShiftBegin) <= 0 && endTime.compareTo(nextCurShiftEnd) > 0)) {
                        throw BusinessException.build("班次【" + shift + "】与工作中心下已存在班次【" + wcShift + "】时间交叉");
                    }
                }
            }
        }
    }

    /**
     * 标准功能-用户班次时间处理
     *
     * @param list
     * @return
     */
    public List<WorkCenterShiftView> resetUserShiftDateTime(List<WorkCenterShiftView> list) {

        if (list.size() > 0) {

            for (WorkCenterShiftView map : list) {
                //缓存处理
                if ("Y".equalsIgnoreCase((String) map.getConvert())) {
                    continue;
                }
                String beginTime = map.getBeginTime();
                beginTime = TimeUtils.stringToTime(beginTime);
                map.setBeginTime(beginTime);

                String endTime = map.getEndTime();
                endTime = TimeUtils.stringToTime(endTime);
                map.setEndTime(endTime);

                if (StringUtils.notBlank(map.getClockInStartTime())) {
                    String clockInStartTime = map.getClockInStartTime();
                    clockInStartTime = TimeUtils.stringToTime(clockInStartTime);
                    map.setClockInStartTime(clockInStartTime);
                }
                map.setConvert("Y");
            }
        }
        return list;
    }

    public List<WorkCenterShiftView> getEnabledShiftsByWorkCenter(String site, String workCenter) {

        //查询所有班次
        Locale locale = LocaleContextHolder.getLocale();
        List<WorkCenterShiftView> list = workCenterShiftMapper.selectEnabledShiftsByWorkCenter(site, workCenter, locale.getLanguage());

        if (list.size() > 0) {

            for (WorkCenterShiftView workCenterShiftView : list) {
                //缓存处理
                if ("Y".equalsIgnoreCase((String) workCenterShiftView.getConvert())) {
                    continue;
                }
                String beginTime = workCenterShiftView.getBeginTime();
                beginTime = TimeUtils.stringToTime(beginTime);
                workCenterShiftView.setBeginTime(beginTime);

                String endTime = workCenterShiftView.getEndTime();
                endTime = TimeUtils.stringToTime(endTime);
                workCenterShiftView.setEndTime(endTime);

                if (StringUtils.notBlank(workCenterShiftView.getClockInStartTime())) {
                    String clockInStartTime = workCenterShiftView.getClockInStartTime();
                    clockInStartTime = TimeUtils.stringToTime(clockInStartTime);
                    workCenterShiftView.setClockInStartTime(clockInStartTime);
                }
                workCenterShiftView.setConvert("Y");
            }
        }
        return list;
    }
}